package com.zzyl.nursing.service.impl;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zzyl.common.exception.base.BaseException;
import com.zzyl.common.utils.CodeGenerator;
import com.zzyl.common.utils.DateUtils;
import com.zzyl.nursing.domain.*;
import com.zzyl.nursing.dto.CheckInApplyDto;
import com.zzyl.nursing.dto.CheckInConfigDto;
import com.zzyl.nursing.dto.CheckInContractDto;
import com.zzyl.nursing.dto.CheckInElderDto;
import com.zzyl.nursing.mapper.*;
import com.zzyl.nursing.vo.CheckInConfigVo;
import com.zzyl.nursing.vo.CheckInDetailVo;
import com.zzyl.nursing.vo.CheckInElderVo;
import com.zzyl.nursing.vo.ElderFamilyVo;
import nonapi.io.github.classgraph.json.JSONUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.zzyl.nursing.service.ICheckInService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

/**
 * 入住Service业务层处理
 * 
 * @author alexis
 * @date 2025-08-09
 */
@Service
public class CheckInServiceImpl extends ServiceImpl<CheckInMapper, CheckIn> implements ICheckInService
{
    @Autowired
    private CheckInMapper checkInMapper;
    @Autowired
    private CheckInConfigMapper checkInConfigMapper;
    @Autowired
    private ContractMapper contractMapper;
    @Autowired
    private ElderMapper elderMapper;
    @Autowired
    private BedMapper bedMapper;


            /**
             * 查询入住
             * 
             * @param id 入住主键
             * @return 入住
             */
    @Override
    public CheckIn selectCheckInById(Long id)
    {
        return getById(id);
    }

    /**
     * 查询入住列表
     * 
     * @param checkIn 入住
     * @return 入住
     */
    @Override
    public List<CheckIn> selectCheckInList(CheckIn checkIn)
    {
        return checkInMapper.selectCheckInList(checkIn);
    }

    /**
     * 新增入住
     * 
     * @param checkIn 入住
     * @return 结果
     */
    @Override
    public int insertCheckIn(CheckIn checkIn)
    {
        return save(checkIn) ? 1 : 0;
    }

    /**
     * 修改入住
     * 
     * @param checkIn 入住
     * @return 结果
     */
    @Override
    public int updateCheckIn(CheckIn checkIn)
    {
        return updateById(checkIn) ? 1 : 0;
    }

    /**
     * 批量删除入住
     * 
     * @param ids 需要删除的入住主键
     * @return 结果
     */
    @Override
    public int deleteCheckInByIds(Long[] ids)
    {
        return removeByIds(Arrays.asList(ids)) ? 1 : 0;
    }

    /**
     * 删除入住信息
     * 
     * @param id 入住主键
     * @return 结果
     */
    @Override
    public int deleteCheckInById(Long id)
    {
        return removeById(id) ? 1 : 0;
    }

    /**
     * 入住申请
     * @param checkInApplyDto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void apply(CheckInApplyDto checkInApplyDto) {

        //1.校验老人是否已经入住,如果已经入住就抛出一个异常 通过传递过来的身份证号和状态进行查找

        LambdaQueryWrapper<Elder> lambdaQueryWrapper = new LambdaQueryWrapper();
        lambdaQueryWrapper.eq(Elder::getIdCardNo,checkInApplyDto.getCheckInElderDto().getIdCardNo())
                        .in(Elder::getStatus,1,4);//状态是1和4都不行
        Elder elder = elderMapper.selectOne(lambdaQueryWrapper);
        //判断是否存在
        if(!ObjectUtils.isEmpty(elder))
        {
            throw new BaseException("老人已入住,请勿重复入住");
        }

        //2.更新床位状态为已入住  (根据床位id修改床位当前状态)
        Bed bed = bedMapper.selectById(checkInApplyDto.getCheckInConfigDto().getBedId());
        bed.setBedStatus(1);
        bedMapper.updateById(bed);

        //3.新增/跟新老人基本信息(就是可以之前这个老人入住过)
        elder =insertOrUpdateElder(checkInApplyDto.getCheckInElderDto(),bed);//这个elder中又老人id和老人name

        //4.新增签约办理
           //合同表中需要老人id和老人name
           //合同编号用工具类自己生成一个
        String contractNumber = "HT" + CodeGenerator.generateContractNumber();

        insertContract(elder,checkInApplyDto,contractNumber);

        //5.新增入住信息
        CheckIn checkIn = insertCheckInfo(elder, checkInApplyDto);

        //6.新增入住配置信息
        insertCheckInConfig(checkIn,checkInApplyDto);

    }

    /**
     * 查看入住详情
     * @param id
     * @return
     */
    @Override
    public CheckInDetailVo selectCheckInDetailById(Long id) {
        CheckInDetailVo checkInDetailVo = new CheckInDetailVo();
        //1.查询老人基本信息
        CheckIn checkIn = selectCheckInElderVo(id, checkInDetailVo);

        //2.查询老人家属信息(在checkin中的remark中)
        String remark = checkIn.getRemark();
        //将json格式的字符串转换成list集合
        List<ElderFamilyVo> list=(List<ElderFamilyVo>) JSON.parse(remark);
        checkInDetailVo.setElderFamilyVoList(list);

        //3.查询入住配置信息
        selectCheckInConfigVo(checkIn,checkInDetailVo);

        //4.查询合同信息
          //根据老人id查找合同对象
        Long elderId = checkIn.getElderId();

        LambdaQueryWrapper<Contract> qw = new LambdaQueryWrapper<>();
                qw.eq(Contract::getElderId,elderId);
        Contract contract = contractMapper.selectOne(qw);
        checkInDetailVo.setContract(contract);

        return checkInDetailVo;
    }

    private void selectCheckInConfigVo(CheckIn checkIn, CheckInDetailVo checkInDetailVo) {

        CheckInConfigVo checkInConfigVo = new CheckInConfigVo();
        //1.根据将 入住配置信息属性 拷贝到 checkinConfigVo中
          //找到数据库中的 入住配置信息对象
        LambdaQueryWrapper<CheckInConfig> qw=new LambdaQueryWrapper<>();
        qw.eq(CheckInConfig::getCheckInId,checkIn.getId());//根据id
        CheckInConfig checkInConfig = checkInConfigMapper.selectOne(qw);

         BeanUtils.copyProperties(checkInConfig,checkInConfigVo);

         //2.设置开始时间和结束时间
        checkInConfigVo.setStartDate(checkIn.getStartDate());
        checkInConfigVo.setEndDate(checkIn.getEndDate());

        //3.设置床位编号(从老人表中可以获取)
        Long elderId = checkIn.getElderId();
        Elder elderInDB = elderMapper.selectById(elderId);
        checkInConfigVo.setBedNumber(elderInDB.getBedNumber());

        //响应数据
        checkInDetailVo.setCheckInConfigVo(checkInConfigVo);
    }

    /**
     * 返回老人基本信息
     * @param id
     * @param checkInDetailVo
     */
    private CheckIn selectCheckInElderVo(Long id,CheckInDetailVo checkInDetailVo) {
        //1.查询checkinElderVo的数据  根据入住id查老人id,根据找到的老人对象的属性拷贝到chekinElderVo对象中
        CheckInElderVo checkInElderVo = new CheckInElderVo();
        CheckIn checkIn = checkInMapper.selectCheckInById(id);
        Long elderId = checkIn.getElderId();
        Elder elderInDB = elderMapper.selectById(elderId);
        //属性拷贝
        BeanUtils.copyProperties(elderInDB,checkInElderVo);

        //这里的年龄要进行计算一下
        //现在的时间减去出生日期等于年龄
        LocalDate date = LocalDateTime.now().toLocalDate();
        //将字符串转换成时间格式
        String birthday = elderInDB.getBirthday();
        LocalDate birth = LocalDate.parse(birthday, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        checkInElderVo.setAge(date.getYear()-birth.getYear());

        checkInDetailVo.setCheckInElderVo(checkInElderVo);
        return checkIn;
    }

    /**
     * 新增入住配置信息
     * @param checkIn
     * @param checkInApplyDto
     */
    private void insertCheckInConfig(CheckIn checkIn, CheckInApplyDto checkInApplyDto) {
        CheckInConfig checkInConfig = new CheckInConfig();

        checkInConfig.setCheckInId(checkIn.getId());

        BeanUtils.copyProperties(checkInApplyDto.getCheckInConfigDto(),checkInConfig);

        checkInConfigMapper.insert(checkInConfig);
    }

    /**
     * 插入入住基本信息
     * @param elder
     * @param checkInApplyDto
     */
    private CheckIn insertCheckInfo(Elder elder, CheckInApplyDto checkInApplyDto) {
        CheckIn checkIn = new CheckIn();
        //设置老人id和name
        checkIn.setElderId(elder.getId());
        checkIn.setElderName(elder.getName());
        //设置入住开始时间和结束时间和状态
        LocalDateTime startDate = checkInApplyDto.getCheckInConfigDto().getStartDate();
        LocalDateTime endDate = checkInApplyDto.getCheckInConfigDto().getEndDate();
        checkIn.setStartDate(startDate);
        checkIn.setEndDate(endDate);
        checkIn.setStatus(0);

        //设置bed_number
        checkIn.setBedNumber(elder.getBedNumber());

        //将家庭集合信息转换成json格式的字符串,传入remark中
        checkIn.setRemark(JSON.toJSONString(checkInApplyDto.getElderFamilyDtoList()));

        BeanUtils.copyProperties(checkInApplyDto.getCheckInConfigDto(),checkIn);
        BeanUtils.copyProperties(checkInApplyDto.getCheckInElderDto(),checkIn);

        checkInMapper.insert(checkIn);
        return checkIn;
    }


    /**
     * 插入合同信息
     * @param elder
     * @param checkInApplyDto
     * @param contractNumber
     */
    private void insertContract(Elder elder, CheckInApplyDto checkInApplyDto, String contractNumber) {
        Contract contract=new Contract();
        BeanUtils.copyProperties(checkInApplyDto.getCheckInContractDto(),contract);
        //设置老人id和name
        contract.setElderId(elder.getId());
        contract.setElderName(elder.getName());
        //设置合同编号
        contract.setContractNumber(contractNumber);
        //设置开始日期和结束日期和合同状态
        LocalDateTime startDate = checkInApplyDto.getCheckInConfigDto().getStartDate();
        LocalDateTime endDate = checkInApplyDto.getCheckInConfigDto().getEndDate();
        contract.setStartDate(startDate);
        contract.setEndDate(endDate);
        //根据开始时间和结束时间判断当前这个合同的状态
        int status=startDate.isAfter(LocalDateTime.now())? 0 : 1;
        contract.setStatus(status);
        contractMapper.insert(contract);//插入数据
    }


    /**
     * 新增/更新老人信息
     * @param checkInElderDto
     * @param bed
     * @return
     */
    private Elder insertOrUpdateElder(CheckInElderDto checkInElderDto, Bed bed) {
        Elder elder = new Elder();//这个老人对象是传递过来的数据,这里面就由身份证和状态,根据这两个信息就可以判断是新增还是更新了
        elder.setBedId(bed.getId());
        elder.setBedNumber(bed.getBedNumber());
        BeanUtils.copyProperties(checkInElderDto,elder);

        //判断老人是新增/更新(根据传递过来的通过身份证号和状态(除了1和4))
        LambdaQueryWrapper<Elder>queryWrapper=new LambdaQueryWrapper();
        queryWrapper.eq(Elder::getIdCardNo,elder.getIdCardNo())
                        .notIn(Elder::getStatus,elder.getStatus());
        Elder elderInDB = elderMapper.selectOne(queryWrapper);//这个是数据库中找到的elder对象
        if(ObjectUtils.isNotEmpty(elderInDB))
        {
            //更新操作
            elder.setId(elderInDB.getId());
            elderMapper.updateById(elder);//根据id修改elderInDB对象
            return elder;
        }else
        {
            //新增操作
            elderMapper.insert(elder);
            return elder;
        }

    }
}
